#include<iostream>
#include"../comm/jsoncpp.hpp"
#include"../comm/httplib.h"
#include"Controler.hpp"
#include"../comm/FileTools.hpp"
#include"../comm/log.hpp"
using namespace std;

using namespace httplib;
using namespace Ns_Con;
using namespace Ns_FileTools;
using namespace Ns_Log;
int main()
{
    Server s;
    Controler con;
    s.Get("/test",[&con](const Request& req,Response& rep)//访问登录主页
    {
        rep.set_content("hello","text/html;charset=UTF-8");
    });
    s.Get("/",[&con](const Request& req,Response& rep)//访问登录主页
    {
        //检查cookie
        //log(INFO,"请求根");
        if(con.check_cookie(req.get_header_value("Cookie")))
        {
            rep.set_redirect("questions_page");//Cookie验证通过，直接进入主页
        }
        else
        rep.set_redirect("entry/index.html");//cookie验证不通过，重定向到登录页面
    });
    s.set_base_dir("./WebRoot");//设置web默认根目录

    s.Post("/login",[&con](const Request& req,Response& rep)//登录逻辑，负责验证账号密码，返回true or false
    {
        log(INFO,"登录请求");
        string userid=req.get_file_value("userid").content;
        string password=req.get_file_value("password").content;
        if(con.login(userid,password))
        {
            rep.set_content("{\"status\":\"true\"}","application/json");
            rep.set_header("Set-Cookie","userid="+userid);
            rep.set_header("Set-Cookie","password="+password);
            log(INFO,"用户"+userid+"登录成功");
        }
        else
        {
            rep.set_content("{\"status\":\"false\"}","application/json");
            log(INFO,"用户"+userid+"登录失败");
        }
        
    });
    s.Post("/regist",[&con](const Request& req,Response& rep)//注册逻辑，获取输入框内的各种信息，插入到数据库中
    {
        log(INFO,"注册请求");
        string userid=req.get_file_value("userid").content;
        string password=req.get_file_value("password").content;
        string gender=req.get_file_value("gender").content;
        string age=req.get_file_value("age").content;
        string email=req.get_file_value("email").content;
        string name=req.get_file_value("nickname").content;
        string signature=req.get_file_value("signature").content;
        if(con.regist(userid,password,gender,age,email,name,signature))
        {
            //注册成功，跳转登录界面
            rep.set_content("{\"status\":\"true\"}","application/json");
            log(INFO,"用户"+userid+"注册成功");
        }
        else
        {
            rep.set_content("{\"status\":\"false\"}","application/json");
            log(INFO,"用户"+userid+"注册失败");
            //注册失败，提示用户
        }
    });
    s.Get("/questions_page",[&con](const Request& req,Response& rep)//逻辑API，无脑返回模板网页，再通过js请求数据API，拿到数据进行渲染
    {
        //Request:{}
        //读取index.html并返回
        //检查cookie
        log(INFO,"请求问题列表的html模板");

        if(con.check_cookie(req.get_header_value("Cookie")))
        {
            rep.set_redirect("/questions_list/index.html",200);//用户直接访问/questions_list/index.html怎么办
        }
        else
        {
            rep.set_redirect("/simple/login.html",302);
        }
    });
    s.Get("/question_page",[&con](const Request& req,Response& rep)//逻辑API，读取模板网页
    {
        //Request:{}
        //读取problem.html并返回
        log(INFO,"请求问题的html模板");
        if(con.check_cookie(req.get_header_value("Cookie")))
        {
            string outstring;
            FileTools::ReadFileToString("./WebRoot/question_template/problem.html",outstring);
            rep.set_content(outstring,"text/html");
        }
        else
        {
            rep.set_redirect("/simple/login.html",302);
        }
    });

    s.Get("/questions_data",[&con](const Request& req,Response& rep)//数据API
    {
        //Request:{}
        //返回json格式的问题列表{{"id":"1",},{}}
        log(INFO,"请求问题列表数据");
        std::vector<Question> qv;
        if(con.get_questions(&qv))
        {
            // 序列化
            Json::Value root;
            for (size_t i = 0; i < qv.size(); i++) {
                Json::Value ques;
                ques["qid"] = to_string(qv[i]._id);
                ques["qname"] = qv[i]._qname;
                ques["qlevel"] = qv[i]._qlevel;
                root.append(ques);
            }
            string resp_json;
            Serialize(root,resp_json);
            
            rep.set_content(resp_json,"application/json");
        }
        else
        {
            log(ERROR,"请求问题列表数据失败");
            rep.status=404;
        }
    });
    s.Get(R"(/question_data_(\d+))",[&con](const Request& req,Response& rep)//数据API
    {
        //Request:{}
        //从请求中获取题号
        log(INFO,"请求某个问题数据");
        string number=req.matches[1];
        //构建响应
        Question q;
        string code;
        if(con.get_question(stoi(number),&q)&&con.get_latest_code(req.get_header_value("Cookie"),number,code))
        {
            //序列化
            Json::Value root;
            root["qid"]=to_string(q._id);
            root["qname"]=q._qname;
            root["qlevel"]=q._qlevel;
            root["qdisc"]=q._qdisc;
            root["t_limit"]=q._t_limit;
            root["s_limit"]=q._s_limit;
            root["qcue"]=q._qcue;
            root["code"]=code;
            
            string resp_json;
            Serialize(root,resp_json); 
            rep.set_content(resp_json,"application/json");
        }
        else
        {
            rep.set_content("no data","text/html;charset=UTF-8");
        }
        
    });
    s.Get(R"(/submitrecord_(\d+))",[&con](const Request& req,Response& rep)
    {
        log(INFO,"用户请求提交记录");
        string qid=req.matches[1];;//题号

        vector<AnswerStatus> v;
        if(con.get_question_submit_record(req.get_header_value("Cookie"),qid,v))
        {
            Json::Value root;
            for (size_t i = 0; i < v.size(); i++) {
                Json::Value sub_red;
                sub_red["status"] = v[i]._status;
                sub_red["date"]=v[i]._date;
                root.append(sub_red);
            }
            
            string resp_json;
            Serialize(root,resp_json); 
            rep.set_content(resp_json,"application/json");
        }
        else
        {
            log(ERROR,"controler获取一道题最近提交记录失败，原因：数据库sql执行失败");
            rep.set_content("{\"status\":\"false\"}","application/json");
        }
    });
    s.Post("/judge",[&con](const Request& req,Response& rep)
    {
        log(INFO,"用户请求判题");
        if(con.check_cookie(req.get_header_value("Cookie")))
        {
            string userid;
            con.get_userid_from_cookie(req.get_header_value("Cookie"),userid);
            //Request:{id:?,code:?}
            Json::Value root;
            UnSerialize(root,req.body);
            string id=root["id"].asString();//题号
            string code=root["code"].asString();//代码
            //通过controler来提交代码
            string passed_status;
            string message;
            con.judge_question(userid,id,code,passed_status,message);
            
            //序列化
            string result_json;
            Json::Value judge_root;
            judge_root["passed_status"]=passed_status;
            judge_root["message"]=message;
            Serialize(judge_root,result_json);
            rep.set_content(result_json,"application/json");
        }
        else
        {
            rep.set_redirect("/simple/login.html",302);
        }
        
    });
    s.Get("/forum",[&con](const Request& req,Response& rep){
        rep.set_content("这里是论坛模块","text/html;charset=UTF-8");
    });
    s.Get("/jobs",[&con](const Request& req,Response& rep){
        rep.set_content("这里是求职模块","text/html;charset=UTF-8");
    });
    s.Get("/contests",[&con](const Request& req,Response& rep){
        rep.set_content("这里是竞赛模块","text/html;charset=UTF-8");
    });
    s.Get("/rankings",[&con](const Request& req,Response& rep){
        //rep.set_content(out_json,"application/json");
        rep.set_redirect("/rankings/index.html",200);
    });
    s.Get("/rankings_data",[&con](const Request& req,Response& rep){
        vector<PersonRecord> vp;
        if(!con.get_rank_data(vp))
        log(ERROR,"获取排行榜信息失败");

        Json::Value root;
        for (size_t i = 0; i < vp.size(); i++) {
            Json::Value person;
            person["rank"]=i+1;
            person["name"] = vp[i]._name;
            person["count"]=vp[i]._passed_questions_count;
            person["probability"]=vp[i]._passing_probability;
            person["signature"]=vp[i]._user_signature;
            root.append(person);
        }
        string rank_resp_json;
        Serialize(root,rank_resp_json); 
        rep.set_content(rank_resp_json,"application/json");
    });

    
    s.listen("0.0.0.0",80);
    return 0;
}
